﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Common;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using System.Diagnostics;
using System.Collections;
using System.Reflection;

namespace HNAT.CapitalRisk.Common
{
    public enum LogType
    {
        Error,
        Warning,
        Info,
        Debug,
        service
    }

    /// <summary>
    /// 日志级别
    /// </summary>
    public enum LogPriorityEnum
    {
        Error = 0,
        Warning = 1,
        Information = 2
    }

    public class LoggerHelper
    {
        public static void WriteError(string pMethodName, Exception pEx, params object[] pParmsForMethod)
        {
            StringBuilder strError = new StringBuilder();
            if (pEx.InnerException != null)
            {
                strError.AppendFormat("Message: {0}", pEx.InnerException.Message).AppendLine();
                strError.AppendFormat("Source: {0}", pEx.InnerException.Source).AppendLine();
                strError.AppendFormat("CallStack: {0}", pEx.InnerException.StackTrace).AppendLine();
            }
            else
            {
                strError.AppendFormat("Message: {0}", pEx.Message).AppendLine();
                strError.AppendFormat("Source: {0}", pEx.Source).AppendLine();
                strError.AppendFormat("CallStack: {0}", pEx.StackTrace).AppendLine();
            }

            try
            {
                strError.AppendLine(GetParameterStrInfo(pParmsForMethod));
            }
            catch (Exception ex)
            {
                strError.AppendFormat("Parameters: 获取参数异常{0}", ex.ToString()).AppendLine();
            }
            
            WriteLog(pMethodName, LogType.Error, strError.ToString());
        }

        private static string GetParameterStrInfo(params object[] pParmsForMethod)
        {
            string ret = string.Empty;

            if (pParmsForMethod != null && pParmsForMethod.Length > 0)
            {
                try
                {
                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine("************************Show Parameters_Start************************");

                    foreach (var item in pParmsForMethod)
                    {
                        if (item == null)
                        {
                            sb.AppendLine("null");
                        }

                        sb.AppendLine(GetRecuriveMemberValueForLog.GetMemberValueString(item));
                    }

                    sb.AppendLine("************************Show Parameters_End************************");
                    ret = sb.ToString();
                }
                catch
                {
                    ret = "获取参数异常";
                }
                
            }
            else
            {
                ret = "(Empty)";
            }

            return ret;
        }

        private static void WriteLog(string pMethodName, LogType pLogType, string pMessage)
        {
            try
            {
                LogEntry entry = new LogEntry();
                entry.TimeStamp = DateTime.Now;
                entry.Message = pMessage;
                entry.Severity = MatchSeverityFromLogType(pLogType);
                entry.ExtendedProperties.Add("Method Name", pMethodName);
                Logger.Write(entry);
            }
            catch (Exception ex)
            {
                //throw ex;
            }
        }

        /// <summary>
        /// 记录正常信息
        /// </summary>
        /// <param name="message"></param>
        /// <param name="catagory"></param>
        public static void WriteInfo(string pMethodName, string message, params object[] pParmsForMethod)
        {
            IDictionary<string, object> dic = new Dictionary<string,object>();
            dic.Add("Method Name", pMethodName);
            dic.Add("Parameter:", GetParameterStrInfo(pParmsForMethod));
            Logger.Write(message, dic);
        }
        private static TraceEventType MatchSeverityFromLogType(LogType pLogType)
        {
            TraceEventType ret = TraceEventType.Error;
            switch (pLogType)
            {
                case LogType.Error:
                    ret = TraceEventType.Error;
                    break;
                case LogType.Warning:
                    ret = TraceEventType.Warning;
                    break;
                case LogType.Info:
                    ret = TraceEventType.Information;
                    break;
                case LogType.Debug:
                    ret = TraceEventType.Verbose;
                    break;
            }

            return ret;
        }
    }

    class GetRecuriveMemberValueForLog
    {
        /// <summary>
        /// 校验是否为.NET内置的类型（如果是可以直接通过ToString获得值）
        /// </summary>
        /// <param name="pType"></param>
        /// <returns></returns>
        public static bool IsSampleType(Type pType)
        {
            return pType.IsEnum || (pType.Namespace == "System" && pType.Assembly.FullName.Contains("mscorlib"));
        }

        public static bool IsSampleType(object pInstance)
        {
            return IsSampleType(pInstance.GetType());
        }

        private const string BLANK_EMPTY = "    ";

        public static string GetMemberValueString(object pInstance)
        {
            return GetMemberValueString("", pInstance);
        }
        /// <summary>
        /// 获取成员的值，以字符串形式返回
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="pBlank"></param>
        /// <param name="pInstance"></param>
        /// <param name="pMember"></param>
        /// <returns></returns>
        private static string GetMemberValueString(string pBlank, object pInstance)
        {
            if ( Convert.ToString(pInstance) == string.Empty ||IsSampleType(pInstance))
            {
                return pBlank + pInstance.ToString();
            }

            Type t = pInstance.GetType();
            StringBuilder sb = new StringBuilder();
            // 第一层
            if (pBlank == string.Empty)
            {
                sb.AppendFormat(pBlank + "Class Type: {0}", t.FullName).AppendLine();
            }
            else
            {
                sb.AppendLine(pBlank + pInstance.ToString());
            }
            sb.AppendLine(pBlank + "-----------------------------");
            PropertyInfo[] pis = t.GetProperties();
            sb.Append(GetPropertyValString(pBlank, pInstance, pis));
            FieldInfo[] fis = t.GetFields();
            sb.Append(GetFieldValString(pBlank, pInstance, fis));
            sb.AppendLine(pBlank + "-----------------------------");
            return sb.ToString();
        }

        /// <summary>
        /// 获取属性字符串
        /// </summary>
        /// <param name="pBlank">生成的字符串换行留白</param>
        /// <param name="pInstance">属性所在的实例对象（通过它才能获得值）</param>
        /// <param name="pProperties">属性列表</param>
        /// <returns></returns>
        private static string GetPropertyValString(string pBlank, object pInstance, PropertyInfo[] pProperties)
        {
            StringBuilder sb = new StringBuilder();
            foreach (PropertyInfo pi in pProperties)
            {
                if (pi.CanRead)
                {
                    string piName = pi.Name;
                    MethodInfo mi = pi.GetGetMethod();
                    object piValue = mi.Invoke(pInstance, null);
                    sb.AppendLine(GetMemberValueFormatString(pBlank, piName, piValue));
                }
            }

            return sb.ToString();
        }

        /// <summary>
        /// 基于属性值或者字段值获取字符串，格式为“属性名称：属性值”
        /// </summary>
        /// <param name="pBlank"></param>
        /// <param name="piName"></param>
        /// <param name="piValue"></param>
        private static string GetMemberValueFormatString(string pBlank, string piName, object piValue)
        {
            StringBuilder sb = new StringBuilder();
            if (piValue == null)
            {
                return string.Format(pBlank + BLANK_EMPTY + "{0}: {1}", piName, piValue);
            }
            // C#内置类型
            if (IsSampleType(piValue))
            {
                sb.AppendFormat(pBlank + BLANK_EMPTY + "{0}: {1}", piName, piValue);
            }
            // 如果返回值为空
            else if (Convert.ToString(piValue).Replace(" ", "") == string.Empty)
            {
                sb.AppendFormat(pBlank + BLANK_EMPTY + "{0}: {1}", piName, "(null)");
            }
            else if (piValue.GetType().IsEnum)
            {
                sb.AppendFormat(pBlank + BLANK_EMPTY + "{0}: {1}", piName, "(null)");
            }
            // 返回值为可枚举的类型
            else if (piValue as IEnumerable != null)
            {
                sb.AppendFormat(pBlank + BLANK_EMPTY + "{0}: ", piName).AppendLine();

                IEnumerable lst = piValue as IEnumerable;
                IEnumerator enumerator = lst.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    object enumItem = enumerator.Current;
                    sb.AppendLine(GetMemberValueString(pBlank + BLANK_EMPTY + BLANK_EMPTY, enumItem));
                }
            }
            else
            {
                sb.AppendFormat(pBlank + BLANK_EMPTY + "{0}: {1}", piName, GetMemberValueString(pBlank + BLANK_EMPTY, piValue));
            }

            return sb.ToString();
        }

        /// <summary>
        /// 获取字段字符串
        /// </summary>
        /// <param name="pBlank">生成的字符串换行留白</param>
        /// <param name="pInstance">属性所在的实例对象（通过它才能获得值）</param>
        /// <param name="pProperties">属性列表</param>
        /// <returns></returns>
        private static string GetFieldValString(string pBlank, object pInstance, FieldInfo[] pProperties)
        {
            StringBuilder sb = new StringBuilder();
            foreach (FieldInfo fi in pProperties)
            {
                string fiName = fi.Name;
                object fiValue = fi.GetValue(pInstance);
                sb.AppendLine(GetMemberValueFormatString(pBlank, fiName, fiValue));
            }

            return sb.ToString();
        }

        private static String GetObjectMemberStringValue()
        {
            return "";
        }

        private static string GetListMemberStringValue(IEnumerable pListMember, object pInstanceID, string pBlank)
        {
            return "";
        }
    }
}
